package com.jade.bss.ec.ware.impl;

import java.util.List;

import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import com.jade.bss.ec.ware.WareException;
import com.jade.bss.ec.ware.WareSpec;
import com.jade.bss.ec.ware.WareSpecDao;
import com.jade.bss.ec.ware.WareSpecDefine;
import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.Restrictions;
import com.jade.framework.base.criterion.sql.SqlUtils;
import com.jade.framework.base.util.PagingList;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;

/**
 * 采用JPA方式实现规格数据访问接口，cache采用申明式，通过注释Annotation来进行描述。
 */
@Named ("bss_wareSpecDao")
public class JpaSpecDao
        implements WareSpecDao
{
    protected static final String SQL_DEFINE = "SELECT specDefine FROM com.jade.bss.ec.ware.WareSpecDefine specDefine";
    protected static final String SQL_SPEC = "SELECT wareSpec FROM com.jade.bss.ec.ware.WareSpec wareSpec";
    @PersistenceContext (unitName = "default")
    protected EntityManager entityManager;

    @Caching (evict = {
            @CacheEvict (value = "bss.ec.ware.spec.ldef", key = "#define.ownerType + '_' + #define.ownerId + '_' + #define.cid + '[%GRP%]'")})
    public void setSpecDefine(WareSpecDefine define)
            throws WareException
    {
        entityManager.merge(define);
    }

    @Cacheable (value = "bss.ec.ware.spec.ldef", key = "#ownerType + '_' + #ownerId + '_' + #cid + '[%GRP%]' + #criteria")
    public List<WareSpecDefine> listSpecDefine(String ownerType, String ownerId, long cid, Criteria criteria)
    {
        criteria.add(Restrictions.eq("ownerType", ownerType));
        criteria.add(Restrictions.eq("ownerId", ownerId));
        criteria.add(Restrictions.eq("cid", cid));
        return SqlUtils.sqlQueryWithoutCount(SQL_DEFINE, entityManager, criteria);
    }


    @Caching (evict = {@CacheEvict (value = "bss.ec.ware.spec.g", key = "#spec.id"),
            @CacheEvict (value = "bss.ec.ware.spec.l", key = "#spec.ownerType + '_' + #spec.ownerId + '_' + #spec.cid + '_' + #spec.type + '[%GRP%]'"),
            @CacheEvict (value = "bss.ec.ware.spec.q", key = "#spec.ownerType + '_' + #spec.ownerId + '_' + #spec.cid + '_' + #spec.type + '[%GRP%]'")})
    public void addSpec(WareSpec spec)
            throws WareException
    {
        entityManager.persist(spec);
    }

    @Caching (evict = {@CacheEvict (value = "bss.ec.ware.spec.g", key = "#spec.id"),
            @CacheEvict (value = "bss.ec.ware.spec.l", key = "#spec.ownerType + '_' + #spec.ownerId + '_' + #spec.cid + '_' + #spec.type + '[%GRP%]'"),
            @CacheEvict (value = "bss.ec.ware.spec.q", key = "#spec.ownerType + '_' + #spec.ownerId + '_' + #spec.cid + '_' + #spec.type + '[%GRP%]'")})
    public void updateSpec(WareSpec spec)
            throws WareException
    {
        entityManager.merge(spec);
    }

    @Caching (evict = {@CacheEvict (value = "bss.ec.ware.spec.g", key = "#spec.id"),
            @CacheEvict (value = "bss.ec.ware.spec.l", key = "#spec.ownerType + '_' + #spec.ownerId + '_' + #spec.cid + '_' + #spec.type + '[%GRP%]'"),
            @CacheEvict (value = "bss.ec.ware.spec.q", key = "#spec.ownerType + '_' + #spec.ownerId + '_' + #spec.cid + '_' + #spec.type + '[%GRP%]'")})
    public void removeSpec(WareSpec spec)
            throws WareException
    {
        WareSpec old = getSpec(spec.getId());
        if (old != null) {
            entityManager.remove(old);
        }
    }

    @Cacheable (value = "bss.ec.ware.spec.g", key = "#id")
    public WareSpec getSpec(long id)
            throws WareException
    {
        return entityManager.find(WareSpec.class, id);
    }

    @Cacheable (value = "bss.ec.ware.spec.l", key = "#ownerType + '_' + #ownerId + '_' + #cid + '_' + #type + '[%GRP%]' + #criteria")
    public List<WareSpec> listSpec(String ownerType, String ownerId, long cid, int type, Criteria criteria)
    {
        criteria.add(Restrictions.eq("ownerType", ownerType));
        criteria.add(Restrictions.eq("ownerId", ownerId));
        criteria.add(Restrictions.eq("cid", cid));
        criteria.add(Restrictions.eq("type", type));
        return SqlUtils.sqlQueryWithoutCount(SQL_SPEC, entityManager, criteria);
    }

    @Cacheable (value = "bss.ec.ware.spec.q", key = "#ownerType + '_' + #ownerId + '_' + #cid + '_' + #type + '[%GRP%]' + #criteria")
    public PagingList<WareSpec> querySpec(String ownerType, String ownerId, long cid, int type, Criteria criteria)
    {
        criteria.add(Restrictions.eq("ownerType", ownerType));
        criteria.add(Restrictions.eq("ownerId", ownerId));
        criteria.add(Restrictions.eq("cid", cid));
        criteria.add(Restrictions.eq("type", type));
        return SqlUtils.sqlQuery(SQL_SPEC, entityManager, criteria);
    }

}
